﻿#region License
// Copyright 2010 Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Globalization;

namespace MediaWiki.Common
{
  public static class StringExtensions
  {
    public static string FormatWith(this string format, params object[] args)
    {
      return string.Format(format, args);
    }

    public static string FormatWith(this string format, CultureInfo cultureInfo, params object[] args)
    {
      return string.Format(cultureInfo, format, args);
    }

    public static string NullTerminate(this string s)
    {
      return s + '\0';
    }

    /// <summary>
    /// Indents each line of the specified string.
    /// </summary>
    /// <param name="s">The string to indent.</param>
    /// <param name="indentation">The number of characters to indent by.</param>
    /// <returns>The indented string.</returns>
    public static string Indent(this string s, int indentation)
    {
      return Indent(s, indentation, ' ');
    }

    /// <summary>
    /// Indents each line of the specified string.
    /// </summary>
    /// <param name="s">The string to indent.</param>
    /// <param name="indentation">The number of characters to indent by.</param>
    /// <param name="indentChar">The indent character.</param>
    /// <returns></returns>
    public static string Indent(this string s, int indentation, char indentChar)
    {
      if (s == null)
        throw new ArgumentNullException("s");

      if (indentation <= 0)
        throw new ArgumentException("Must be greater than zero.", "indentation");

      StringReader sr = new StringReader(s);
      StringWriter sw = new StringWriter();

      ActionTextReaderLine(sr, sw, delegate(TextWriter tw, string line)
      {
        tw.Write(new string(indentChar, indentation));
        tw.Write(line);
      });

      return sw.ToString();
    }

    private delegate void ActionLine(TextWriter textWriter, string line);

    private static void ActionTextReaderLine(TextReader textReader, TextWriter textWriter, ActionLine lineAction)
    {
      string line;
      bool firstLine = true;
      while ((line = textReader.ReadLine()) != null)
      {
        if (!firstLine)
          textWriter.WriteLine();
        else
          firstLine = false;

        lineAction(textWriter, line);
      }
    }

    /// <summary>
    /// Determines whether the string has white space.
    /// </summary>
    /// <param name="s">The string to test for white space.</param>
    /// <returns>
    /// 	<c>true</c> if the string has white space; otherwise, <c>false</c>.
    /// </returns>
    public static bool HasWhiteSpace(this string s)
    {
      if (s == null)
        throw new ArgumentNullException("s");

      for (int i = 0; i < s.Length; i++)
      {
        if (char.IsWhiteSpace(s[i]))
          return true;
      }
      return false;
    }

    /// <summary>
    /// Determines whether the string is all white space. Empty string will return false.
    /// </summary>
    /// <param name="s">The string to test whether it is all white space.</param>
    /// <returns>
    /// 	<c>true</c> if the string is all white space; otherwise, <c>false</c>.
    /// </returns>
    public static bool IsWhiteSpace(this string s)
    {
      if (s == null)
        throw new ArgumentNullException("s");

      if (s.Length == 0)
        return false;

      for (int i = 0; i < s.Length; i++)
      {
        if (!char.IsWhiteSpace(s[i]))
          return false;
      }

      return true;
    }

    public static string Reverse(this string s)
    {
      if (string.IsNullOrEmpty(s))
        return s;

      char[] characters = s.ToCharArray();
      Array.Reverse(characters);
      return new string(characters);
    }

    public static string TrimNonBreakingWhiteSpace(this string s)
    {
      if (string.IsNullOrEmpty(s))
        return s;

      int startIndex = 0;
      int endIndex = 0;
      for (int i = 0; i < s.Length; i++)
      {
        if (!char.IsWhiteSpace(s[i]) || s[i] == '\u00A0')
        {
          startIndex = i;
          break;
        }
      }
      for (int i = s.Length - 1; i >= 0; i--)
      {
        if (!char.IsWhiteSpace(s[i]) || s[i] == '\u00A0')
        {
          endIndex = i + 1;
          break;
        }
      }

      return s.Substring(startIndex, endIndex - startIndex);
    }
  }
}